﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Web.Services.Protocols;

namespace Billing
{
    [global::System.Serializable]
    public class BillingException : Exception
    {
        //
        // For guidelines regarding the creation of new exception types, see
        //    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
        // and
        //    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
        //

        public BillingException() { }
        public BillingException(string message) : base(message) { }
        public BillingException(string message, Exception inner) : base(message, inner) { }
        public BillingException(string action,
                System.Security.Principal.IPrincipal User,
                string ErrorMessage,
                int Code,
                Exception inner)
            : base(ErrorMessage, inner)
        {
            this.Action = action;
            this.Code = Code;
            this.ErrorMessage = ErrorMessage;
        }
        protected BillingException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }

        private string _action;
        private string _errorMessage;
        private int _code;

        internal const string ActionNode = "ActionNode8472193";
        internal const string MessageNode = "MessageNode82749283750";
        internal const string CodeNode = "CodeNode429872983";

        private System.Security.Principal.IPrincipal _user;

        public string Action
        {
            get { return _action; }
            set { _action = value; }
        }
        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { _errorMessage = value; }
        }
        public int Code
        {
            get { return _code; }
            set { _code = value; }
        }


        public static BillingException ConvertFromException(Exception ex)
        {
            if (ex == null)
                return null;

            if (ex is SoapException)
            {
                int code = 0;
                try
                {
                    code = int.Parse(ReadNode(CodeNode, ex as SoapException));
                }
                catch { code = -1; }
                return new BillingException(ReadNode(CodeNode, ex as SoapException), null, ReadNode(MessageNode, ex as SoapException), code, ex);
            }

            if (ex is System.Data.SqlClient.SqlException)
            {
                System.Data.SqlClient.SqlException sx = (ex as System.Data.SqlClient.SqlException);
                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                foreach (System.Data.SqlClient.SqlError er in sx.Errors)
                {
                    if (er.Number >= 50000)
                        sb.AppendLine(er.Message);
                }
                return new BillingException("Not Implemented", null, sb.ToString(), sx.ErrorCode, sx);
            }

            if (ex is ArgumentException)
            {
                ArgumentException ar = (ex as ArgumentException);
                return new BillingException("Not Implamented", null, ar.Message, -1, ex);
            }
            if (ex is BillingException) return ex as BillingException;
            if (ex.InnerException != null)
                return ConvertFromException(ex.InnerException);

            return new BillingException("Not Implemented", null, ex.Message, -1, ex);

        }

        public static SoapException CreateSoapException(string actionName, string message, int code, System.Web.HttpContext context)
        {
            Guard.ArgumentNotNullOrEmptyString(message, "Soap Message");
            Guard.ArgumentNotNull(context, "HttpContext");

            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            System.Xml.XmlNode node = doc.CreateNode(XmlNodeType.Element,
                    SoapException.DetailElementName.Name,
                        SoapException.DetailElementName.Namespace);

            System.Xml.XmlNode messageNode = doc.CreateNode(XmlNodeType.Element,
                MessageNode, "http://CargoService.Railway.ge/");
            messageNode.InnerText = message;

            System.Xml.XmlNode actionNode = doc.CreateNode(XmlNodeType.Element,
                ActionNode, "http://CargoService.Railway.ge/");
            actionNode.InnerText = actionName;

            System.Xml.XmlNode codeNode = doc.CreateNode(XmlNodeType.Element,
                CodeNode, "http://CargoService.Railway.ge/");
            codeNode.InnerText = code.ToString();

            node.AppendChild(actionNode);
            node.AppendChild(messageNode);
            node.AppendChild(codeNode);

            return new SoapException("Fault occurred", SoapException.ClientFaultCode, context.Request.Url.AbsoluteUri, node);
        }

        public static SoapException ConvertToSoapException(Exception x, System.Web.HttpContext context)
        {
            BillingException cex = ConvertFromException(x);
            return CreateSoapException(cex.Action, cex.ErrorMessage, cex.Code, context);
        }

        private static string ReadNode(string node, SoapException ex)
        {
            Guard.ArgumentNotNullOrEmptyString(node, "Node");
            Guard.ArgumentNotNull(ex, "Soap Exception");

            if (ex.Detail == null || ex.Detail[node] == null)
                return string.Empty;
            return ex.Detail[node].InnerText;
        }
    }
}
